#ifndef     __EXECUTOR_H
#define     __EXECUTOR_H

#include "../rtx/rtx_os.h"

namespace rtos {

template <uint32_t STACK_SIZE>
struct ThreadMem {
    uint64_t cb_mem[ (osRtxThreadCbSize + 7) / 8 ];
    uint64_t stack_mem[ (STACK_SIZE + 7) / 8 ];

    osThreadId_t id;

    void start(const char *name = "other") {
        osThreadAttr_t attr;
		attr.name = name;
        attr.attr_bits = osThreadDetached;
        attr.cb_mem = cb_mem;
        attr.cb_size = osRtxThreadCbSize;
        attr.stack_mem = stack_mem;
        attr.stack_size = StackSize;
        attr.priority = Priority;
        attr.tz_module = 0;
        attr.reserved = 0;
        m_id = osThreadNew(exec_main, this, &attr);
    }
};

template <typename TASK, uint8_t THREAD_COUNT, uint32_t STACK_SIZE, osPriority_t PRIORITY>
class Executor {

public:
    void start(const char *name = "other") {
        for (uint8_t i = 0; i < THREAD_COUNT; i ++) {
            start_by_index(name, i);
        }
    }
    

private:
    static void exec_main(void *args) {
        static_cast<TASK *>(args)->run();
    }

    void start_by_index(const char *name, uint8_t index) {
        osThreadAttr_t attr;
        attr.name = "executor";
        attr.attr_bits = osThreadDetached;
        attr.cb_mem = m_task[index].cb_mem;
        attr.cb_size = osRtxThreadCbSize;
        attr.stack_mem = m_task[index].stack_mem;
        attr.stack_size = STACK_SIZE;
        attr.priority = PRIORITY;
        attr.tz_module = 0;
        attr.reserved = 0;
        m_task[index].id = osThreadNew(exec_main, this, &attr);
    }

    ThreadMem<STACK_SIZE> m_task[THREAD_COUNT];
};

}

#endif

